package org.iwidget.desktop.ui;
import org.iwidget.desktop.core.*;
import org.iwidget.desktop.model.*;
import org.iwidget.model.javascript.ScrollElementJS;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
/**
 *
 * @author Muhammad Hakim A
 */

public class WidgetFrame extends TransparentFrame
    implements MouseListener, KeyListener, ActionListener, PopupMenuListener
{
    class MenuThread extends Thread
    {

        public void run()
        {
            String script = action.substring(1);
            try
            {
                widget.executeScript(widget, script, "Menu:" + action);
            }
            catch(Exception ex)
            {
                ex.printStackTrace();
            }
        }

        String action;

        public MenuThread(String action)
        {
            this.action = action;
        }
    }


    public WidgetFrame(WidgetElement widget)
    {
        super(widget);
        this.widget = widget;
        isMoving = false;
        layers = getLayeredPane();
        layers.setBackground(new Color(128, 128, 128, 255));
        layers.setDoubleBuffered(true);
        layers.setSize(widget.getWindowJS().getWidth(), widget.getWindowJS().getHeight());
        buildObjectList();
        createMenu();
        buildCustomMenus();
        createCloseMenu();
        initComponents();
        setSize(widget.getWindowJS().getWidth(), widget.getWindowJS().getHeight());
        setLocation(widget.getWindowJS().getX(), widget.getWindowJS().getY());
        setBackground(new Color(128, 128, 128, 0));
        addMouseListener(this);
        addKeyListener(this);
        setVisible(widget.getWindowJS().getVisible());
        if(widget.getWindowJS().getVisible())
            maketrans();
    }

    public void buildObjectList()
    {
        java.awt.Image lastImage = null;
        if(widget != null && widget.uiObjects != null)
        {
            for(int iCtr = 0; iCtr < widget.uiObjects.size(); iCtr++)
            {
                Object objectJS = widget.uiObjects.get(iCtr);
                if(objectJS instanceof ElementImage)
                {
                    insertImageJS((ElementImage)objectJS);
                    if(iCtr == 0)
                        lastImage = ((ElementImage)objectJS).getImage();
                    continue;
                }
                if(objectJS instanceof ElementTextField)
                {
                    insertTextJS((ElementTextField)objectJS);
                    continue;
                }
                if(objectJS instanceof ElementTextArea)
                {
                    insertTextAreaJS((ElementTextArea)objectJS);
                    continue;
                }
                if(objectJS instanceof ElementScroller)
                    insertScrollerJS((ElementScroller)objectJS);
            }

            if(lastImage != null)
                dragCursor = getToolkit().createCustomCursor(lastImage, new Point(), "Dragger");
            else
                dragCursor = new Cursor(Cursor.MOVE_CURSOR);
        }
    }

    public void insertImageJS(ElementImage imageData)
    {
        WidgetImage imageUI = new WidgetImage(widget, imageData);
        ElementScroller owner = (ElementScroller)imageData.getOwner();
        if(owner == null)
        {
            layers.add(imageUI, JLayeredPane.DEFAULT_LAYER, 0);
        } else
        {
            WidgetScroller scroller = (WidgetScroller)owner.getUIComponent();
            scroller.addWidgetImage(imageUI);
        }
    }

    public void insertTextJS(ElementTextField textData)
    {
        WidgetText textUI = new WidgetText(widget, textData);
        ElementScroller owner = (ElementScroller)textData.getOwner();
        if(owner == null)
        {
            layers.add(textUI, JLayeredPane.DEFAULT_LAYER, 0);
        } else
        {
            WidgetScroller scroller = (WidgetScroller)owner.getUIComponent();
            scroller.addWidgetText(textUI);
        }
    }

    public void insertTextAreaJS(ElementTextArea textData)
    {
        WidgetTextArea textUI = new WidgetTextArea(widget, textData);
        ElementScroller owner = (ElementScroller)textData.getOwner();
        if(owner == null)
        {
            layers.add(textUI, JLayeredPane.DEFAULT_LAYER, 0);
        } else
        {
            WidgetScroller scroller = (WidgetScroller)owner.getUIComponent();
            scroller.addWidgetTextArea(textUI);
        }
    }

    public void insertScrollerJS(ElementScroller data)
    {
        WidgetScroller ui = new WidgetScroller(widget, data);
        layers.add(ui, JLayeredPane.DEFAULT_LAYER, 0);
    }

    public void buildCustomMenus()
    {
        for(int iCtr = 0; iCtr < widget.getMenuElements().size(); iCtr++)
        {
            WidgetMenuElement menuItem = (WidgetMenuElement)widget.getMenuElements().get(iCtr);
            JMenuItem mi = menu.add(new JMenuItem(menuItem.getTitle()));
            mi.setActionCommand("*" + menuItem.getScript());
            mi.addActionListener(this);
        }

    }

    public void resizeComponents()
    {
        setSize(widget.getWindowJS().getWidth(), widget.getWindowJS().getHeight());
        layers.setSize(widget.getWindowJS().getWidth(), widget.getWindowJS().getHeight());
    }

    private void createMenu()
    {
        menu = new JPopupMenu();
        menu.addPopupMenuListener(this);
        if(widget.getAboutElement() != null)
        {
            ArrayList aboutImages = widget.getAboutElement().getImages();
            if(aboutImages.size() > 0)
            {
                JMenuItem mi = menu.add(new JMenuItem("About " + widget.getWindowJS().getTitle()));
                mi.setActionCommand("About");
                mi.addActionListener(this);
                menu.addSeparator();
            }
        }
        boolean foundVisible = false;
        for(int iCtr = 0; iCtr < widget.getPreferenceObjects().size(); iCtr++)
        {
            ElementPreferences pref = (ElementPreferences)widget.getPreferenceObjects().get(iCtr);
            if(pref.getVisible())
                foundVisible = true;
        }

        if(foundVisible)
        {
            JMenuItem mi = menu.add(new JMenuItem("Widget Preferences..."));
            mi.setActionCommand("Preferences");
            mi.addActionListener(this);
        }
    }

    private void createCloseMenu()
    {
        if(widget.getMenuElements().size() > 0)
            menu.addSeparator();
        JMenuItem mi = menu.add(new JMenuItem("Close Widget"));
        mi.setActionCommand("Close");
        mi.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e)
    {
        JMenuItem mi = (JMenuItem)e.getSource();
        // is close operation?
        if(e.getActionCommand().equals("Close"))
        {
            widget.getParent().closeWidget(widget.getWindowJS().getTitle());
            widget = null;
            dispose();
        } else if(e.getActionCommand().equals("About")) // user wanna see about
        {
            //JOptionPane.showConfirmDialog(null,"Test");
            AboutElement about = widget.getAboutElement();
            AboutFrame aboutFrame = new AboutFrame(widget, about);
        } else if(e.getActionCommand().equals("Preferences")) // preferences
            showPreferences();
        else if(e.getActionCommand().startsWith("*"))
            (new MenuThread(e.getActionCommand())).start();
    }

    public void showPreferences()
    {
        PreferenceFrame preferenceFrame = new PreferenceFrame(widget);
    }

    public void showContextMenu()
    {
        if(widget.getWindowJS().getVisible()){
            try
            {
                menu.show(this, widget.getWindowJS().getWidth() / 2, widget.getWindowJS().getHeight() / 2);
            }
            catch(Exception e) { }
        }
    }

    private void handleWindowMove(int x, int y)
    {
        setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
        int dX = x - mX;
        int dY = y - mY;
        if(dX != 0 || dY != 0)
        {
            Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
            int currentX = widget.getWindowJS().getX() + dX;
            int currentY = widget.getWindowJS().getY() + dY;
            if(currentX + widget.getWindowJS().getWidth() >= screen.width)
                currentX = screen.width - widget.getWindowJS().getWidth() - 1;
            if(currentY + widget.getWindowJS().getHeight() >= screen.height)
                currentY = screen.height - widget.getWindowJS().getHeight() - 1;
            if(currentX < 0)
                currentX = 0;
            if(currentY < 0)
                currentY = 0;
            widget.getWindowJS().setX(currentX);
            widget.getWindowJS().setY(currentY);
            setLocation(currentX, currentY);
        }
    }

    public void mousePressed(MouseEvent e)
    {
        if(focusedFrame != this)
        {
            if(focusedFrame != null && focusedFrame.widget != null)
                focusedFrame.widget.triggerEvent("onLoseFocus");
            
            focusedFrame = this;
            requestFocus();
            widget.triggerEvent("onGainFocus");
        }
        
        int button = e.getButton();
        if(Iwidget.osName.equals("Mac OS X")){
            if((e.getModifiers() & 2) == 0)
                button = 1;
            else
                button = 3;
        }
        
        if(button != 3)
        {
            mX = e.getX();
            mY = e.getY();
            widget.triggerEvent("onMouseDown");
        } else
        {
            showContextMenu();
        }
    }

    public void mouseReleased(MouseEvent e)
    {
        int button = e.getButton();
        if(Iwidget.osName.equals("Mac OS X")){
            if((e.getModifiers() & 2) == 0)
                button = 1;
            else
                button = 3;
        }
        if(button != 3)
        {
            widget.triggerEvent("onMouseUp");
            if(isMoving)
            {
                handleWindowMove(e.getX(), e.getY());
                maketrans();
            }
            isMoving = false;
            mY = 0;
            mX = 0;
        }
    }

    public void mouseEntered(MouseEvent e)
    {
        if(widget.getAction("onKeyDown") != null || widget.getAction("onKeyUp") != null || widget.getAction("onKeyPress") != null)
            requestFocus();

        widget.triggerEvent("onMouseEnter");
    }

    public void mouseExited(MouseEvent e)
    {
        if(widget != null)
            widget.triggerEvent("onMouseExit");
    }

    public void mouseClicked(MouseEvent e)
    {
        if(e.getClickCount() == 2)
            maketrans();
    }

    public void mouseDragged(MouseEvent e)
    {
        if(e.getModifiersEx() != 4096 && !isMoving && (Math.abs(e.getX() - mX) > 10 || Math.abs(e.getY() - mY) > 10))
        {
            isMoving = true;
            setCursor(dragCursor);
        }
    }

    public void keyTyped(KeyEvent e)
    {
        widget.triggerEvent("onKeyPress");
    }

    public void keyPressed(KeyEvent e)
    {
        widget.getIwidgetData().key = e.getKeyChar();
        widget.getIwidgetData().keyString = KeyEvent.getKeyText(e.getKeyCode());
        widget.getIwidgetData().keyModifiers = KeyEvent.getKeyModifiersText(e.getModifiers());
        widget.triggerEvent("onKeyDown");
    }

    public void keyReleased(KeyEvent e)
    {
        widget.getIwidgetData().key = e.getKeyChar();
        widget.getIwidgetData().keyString = KeyEvent.getKeyText(e.getKeyCode());
        widget.getIwidgetData().keyModifiers = KeyEvent.getKeyModifiersText(e.getModifiers());
        widget.triggerEvent("onKeyUp");
    }

    public void popupMenuWillBecomeVisible(PopupMenuEvent e)
    {
        for(int iCtr = 0; iCtr < widget.uiObjects.size(); iCtr++)
        {
            Object objectJS = widget.uiObjects.get(iCtr);
            if(!(objectJS instanceof ScrollElementJS))
                continue;
            WidgetScroller scroller = (WidgetScroller)((ScrollElementJS)objectJS).getElementData().getUIComponent();
            if(scroller != null)
                scroller.stopScrolling();
        }

    }

    public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
    {
        for(int iCtr = 0; iCtr < widget.uiObjects.size(); iCtr++)
        {
            Object objectJS = widget.uiObjects.get(iCtr);
            if(!(objectJS instanceof IwidgetScroller))
                continue;
            WidgetScroller scroller = (WidgetScroller)((IwidgetScroller)objectJS).getElementData().getUIComponent();
            if(scroller != null)
                scroller.startScrolling();
        }

    }

    public void popupMenuCanceled(PopupMenuEvent popupmenuevent)
    {
    }

    private static final long serialVersionUID = 0x3831323537383634L;
    private static WidgetFrame focusedFrame;
    private WidgetElement widget;
    private JPopupMenu menu;
    private JLayeredPane layers;
    private boolean isMoving;
    private int mX;
    private int mY;
    private Cursor dragCursor;
    private int iPos;

}